package com.runa.rccprotocol.netservice.modbus;

import com.runa.protocol.dto.ModbusPoint;
import com.runa.protocol.util.ByteUtil;
import com.runa.protocol.util.DigitalUtil;
import com.runa.rccprotocol.dto.ConcentratorRequestData;

import java.util.List;

/**
 * 2024/9/2 16:14
 * zhangYB
 */
public class ModbusRequest extends ConcentratorRequestData {

    private byte[] requestData;

    private List<ModbusPoint> modbusPoints;

    private Integer slaveId;
    private Integer startAddress;
    private Integer registerCount;

    public ModbusRequest(String address) {
        super(address);
        setHaveResult(true);
    }

    public Integer getSlaveId() {
        return slaveId;
    }

    public void setSlaveId(Integer slaveId) {
        this.slaveId = slaveId;
    }

    public Integer getStartAddress() {
        return startAddress;
    }

    public void setStartAddress(Integer startAddress) {
        this.startAddress = startAddress;
    }

    public Integer getRegisterCount() {
        return registerCount;
    }

    public void setRegisterCount(Integer registerCount) {
        this.registerCount = registerCount;
    }

    public List<ModbusPoint> getModbusPoints() {
        return modbusPoints;
    }

    public void setModbusPoints(List<ModbusPoint> modbusPoints) {
        this.modbusPoints = modbusPoints;
    }

    @Override
    public byte[] getData() {
        return requestData;
    }

    public void readHdModbusData(Integer slaveId) {
        this.slaveId = slaveId;
        this.startAddress = modbusPoints.get(0).getRegisterAddress();
        ModbusPoint modbusPoint = modbusPoints.get(modbusPoints.size() - 1);
        this.registerCount = modbusPoint.getRegisterAddress() + modbusPoint.getRegisterCount() - startAddress;
        readHdModbusData();
    }

    private void readHdModbusData() {
        requestData = new byte[24];
        int index = 0;
        requestData[index++] = 0x7b;
        requestData[index++] = (byte)0x89;
        requestData[index++] = 0x00;
        requestData[index++] = 0x18;
        byte[] serialBytes = address.getBytes();
        System.arraycopy(serialBytes, 0, requestData, index, serialBytes.length);
        index += 11;

        byte[] modbusData = getReadModbusData(slaveId, 3, startAddress, registerCount);
        for (int j = 0; j < modbusData.length; j++) {
            requestData[index++] = modbusData[j];
        }
        requestData[index] = 0x7b;
    }


    public void readZdModbusData(Integer slaveId, Integer functionCode) {
        this.slaveId = slaveId;
        this.startAddress = modbusPoints.get(0).getRegisterAddress();
        ModbusPoint modbusPoint = modbusPoints.get(modbusPoints.size() - 1);
        this.registerCount = modbusPoint.getRegisterAddress() + modbusPoint.getRegisterCount() - startAddress;

        //14位编号
        String hexS = "68 14 00 14 00 68 " +
                "41 02 37 01 00 00 " +
                "55 E0 00 00 01 00 " +
                "01 03 00 00 00 00 00 00 " +
                "65 16";
        requestData = ByteUtil.hexStringToByte(hexS);
        int index = 18;
        byte[] modbusBytes = getReadModbusData(slaveId, Integer.valueOf(functionCode), startAddress, registerCount);
        for (int i = 0; i < modbusBytes.length; i++) {
            requestData[index++] = modbusBytes[i];
        }
        requestData[requestData.length - 2] = ByteUtil.sum(requestData, 6, 20);

    }


    public void readFourGModbusData(Integer slaveId) {
        this.slaveId = slaveId;
        this.startAddress = modbusPoints.get(0).getRegisterAddress();
        ModbusPoint modbusPoint = modbusPoints.get(modbusPoints.size() - 1);
        this.registerCount = modbusPoint.getRegisterAddress() + modbusPoint.getRegisterCount() - startAddress;

        requestData = getReadModbusData(slaveId, 3, startAddress, registerCount);
    }


    public void writeFourGModbusData(Integer slaveId, int startAddress, byte[] writeData) {
        this.slaveId = slaveId;
        this.startAddress = startAddress;
        this.registerCount = writeData.length >> 1;
        requestData = getWriteModbusData(slaveId, 0x10, startAddress, registerCount, writeData);
    }

    public byte[] getReadModbusData(Integer slaveId) {
        this.slaveId = slaveId;
        this.startAddress = modbusPoints.get(0).getRegisterAddress();
        ModbusPoint modbusPoint = modbusPoints.get(modbusPoints.size() - 1);
        this.registerCount = modbusPoint.getRegisterAddress() + modbusPoint.getRegisterCount() - startAddress;
        return getReadModbusData(slaveId, 3, startAddress, registerCount);
    }

    public byte[] getReadModbusData(byte slaveId, byte functionCode, Integer index, Integer registerCount) {
        byte[] modbusData = new byte[8];
        modbusData[0] = slaveId;
        modbusData[1] = functionCode;

        modbusData[2] = (byte)(index >> 8 & 0xff);
        modbusData[3] = (byte)(index & 0xff);

        modbusData[4] = (byte)(registerCount >> 8 & 0xff);
        modbusData[5] = (byte)(registerCount & 0xff);

        int crc = DigitalUtil.calcCrc16(modbusData, 6);
        modbusData[6] = (byte) (crc & 0xff);
        modbusData[7] = (byte) (crc >> 8);

        return modbusData;
    }

    public byte[] getReadModbusData(Integer slaveId, Integer functionCode, Integer index, Integer registerCount) {
        byte[] modbusData = new byte[8];
        modbusData[0] = (byte)(slaveId & 0xff);
        modbusData[1] = (byte)(functionCode & 0xff);

        modbusData[2] = (byte)(index >> 8 & 0xff);
        modbusData[3] = (byte)(index & 0xff);

        modbusData[4] = (byte)(registerCount >> 8 & 0xff);
        modbusData[5] = (byte)(registerCount & 0xff);

        int crc = DigitalUtil.calcCrc16(modbusData, 6);
        modbusData[6] = (byte) (crc & 0xff);
        modbusData[7] = (byte) (crc >> 8);

        return modbusData;
    }

    public byte[] getWriteModbusData(Integer slaveId, Integer functionCode, Integer index, Integer registerCount, byte[] value) {
        byte[] modbusData = new byte[9+value.length];
        int i = 0;
        modbusData[i++] = (byte)(slaveId & 0xff);
        modbusData[i++] = (byte)(functionCode & 0xff);

        modbusData[i++] = (byte)(index >> 8 & 0xff);
        modbusData[i++] = (byte)(index & 0xff);

        modbusData[i++] = (byte)(registerCount >> 8 & 0xff);
        modbusData[i++] = (byte)(registerCount & 0xff);

        modbusData[i++] = (byte)(registerCount << 1 & 0xff);

        for (byte b : value) {
            modbusData[i++] = b;
        }

        int crc = DigitalUtil.calcCrc16(modbusData, i);
        modbusData[i++] = (byte) (crc & 0xff);
        modbusData[i++] = (byte) (crc >> 8);

        return modbusData;
    }

    public static void main(String[] args) {
        ModbusRequest modbusRequest = new ModbusRequest("");
        byte[] writeModbusData = modbusRequest.getWriteModbusData(1, 0x10, 0, 1, new byte[2]);
        System.out.println(ByteUtil.byteToHexString(writeModbusData));


    }

}
